home *** CD-ROM | disk | FTP | other *** search
/ OpenGL Superbible (2nd Edition) / OpenGL SuperBible e2.iso / tools / GLUT-3.7 / PROGS / advanced97 / TEXPAGE.C < prev    next >
Encoding:
C/C++ Source or Header  |  1998-08-12  |  11.5 KB  |  504 lines

  1. #include "stdlib.h"
  2. #include "stdio.h"
  3. #include "math.h"
  4. #include <GL/glut.h>
  5. #include "texture.h"
  6. #include "string.h"
  7.  
  8. #if !defined(GL_VERSION_1_1) && !defined(GL_VERSION_1_2)
  9. #define glTexSubImage2D    glTexSubImage2DEXT
  10. #endif
  11.  
  12. static unsigned *image, *bgdtile;
  13. static int width, height, components;
  14. static int grid, zoom, texture;
  15.  
  16.  
  17. #define TSIZE 128
  18. #define TILES 16
  19. #define TILESIZE 32
  20. static struct tile {
  21.     void *data;
  22. } tiles[TILES][TILES];
  23.  
  24. static int x = TILES*TILESIZE/2, y = TILES*TILESIZE/2;
  25.  
  26. /*
  27.  * make an rgb tile for the background.
  28.  */
  29. static void
  30. background_tile(void) {
  31.     int i,j,grid;
  32.     unsigned char *ptr;
  33.  
  34.     bgdtile = (unsigned *) malloc(TILESIZE*TILESIZE*sizeof(unsigned));
  35.     grid = 8;
  36.     ptr = (unsigned char *) bgdtile;
  37.     for (i=0; i<TILESIZE; i++) {
  38.     for(j=0; j<TILESIZE; j++) {
  39.        if(i%grid == 0 || j%grid == 0) {
  40.         *ptr++ = 0x0; *ptr++ = 0x0; *ptr++ = 0x40; ptr++;
  41.        } else {
  42.         *ptr++ = 0x40; *ptr++ = 0x40; *ptr++ = 0x40; ptr++;
  43.        }
  44.         }
  45.     }
  46. }
  47.  
  48. static void
  49. tile_image(unsigned *image) {
  50.     int i, j;
  51.     int w = width/TILESIZE;
  52.     int h = height/TILESIZE, w2 = w/2, h2 = h/2;
  53.     background_tile();
  54.  
  55.     for(i = 0; i < TILES; i++) {
  56.     for(j = 0; j < TILES; j++) {
  57.         if (i >= TILES/2-w2 && i < TILES/2-w2+w && j >= TILES/2-h2 && j < TILES/2-h2+h) {
  58.         /* interior */
  59.         int x, y, k;
  60.         tiles[j][i].data = malloc(TILESIZE*TILESIZE*sizeof(*image));
  61.         x = TILESIZE*(i-TILES/2+w2);
  62.         y = TILESIZE*(j-TILES/2+h2);
  63.         for(k = 0; k < TILESIZE; k++)
  64.             memcpy((unsigned *)tiles[j][i].data+k*TILESIZE,
  65.                 image+width*(y+k)+x, TILESIZE*sizeof *image);
  66.         }
  67.         else
  68.         tiles[j][i].data = bgdtile;
  69.     }
  70.     }
  71.     for(i = 0; i < TILES; i++) {
  72.     for(j = 0; j < TILES; j++) {
  73.         printf("%d ", tiles[j][i].data != bgdtile);
  74.     }
  75.     printf("\n");
  76.     }
  77. }
  78.  
  79. #define MAXMESH 64
  80.  
  81. static float Ml[4*2*(MAXMESH+1)*2 * (MAXMESH+1)];
  82.  
  83. static void
  84. mesh0(float x0, float x1, float y0, float y1,
  85.           float s0, float s1, float t0, float t1, float z, int nx,int ny)
  86. {
  87.     float y,x,s,t,dx,dy,ds,dt,vb[3],tb[2];
  88.     float *mp = Ml;
  89.     
  90.     dx = (x1-x0)/nx;
  91.     dy = (y1-y0)/ny;
  92.     ds = (s1-s0)/nx;
  93.     dt = (t1-t0)/ny;
  94.     y = y0;
  95.     t = t0;
  96.     vb[2] = z;
  97.     while (y < y1) {
  98.         x = x0;
  99.         s = s0;
  100.         while(x <= x1) {
  101.             tb[0] = s; tb[1] = t;
  102.             vb[0] = x; vb[1] = y;
  103.             vb[2] = 0.0;
  104.             *mp++ = tb[0];    
  105.             *mp++ = tb[1];    
  106.             mp += 2;
  107.             *mp++ = vb[0];    
  108.             *mp++ = vb[1];    
  109.             *mp++ = vb[2];    
  110.             mp++;
  111.             tb[1] = t+dt;
  112.             vb[1] = y+dy;
  113.             vb[2] = 0.0;
  114.             *mp++ = tb[0];    
  115.             *mp++ = tb[1];    
  116.             mp += 2;
  117.             *mp++ = vb[0];    
  118.             *mp++ = vb[1];    
  119.             *mp++ = vb[2];    
  120.             mp++;
  121.             x += dx;
  122.             s += ds;
  123.         }    
  124.         y += dy;
  125.         t += dt;
  126.     }
  127. }
  128.  
  129. static void
  130. drawmesh(int nx,int ny) {
  131.     float *mp = Ml;
  132.     int i,j;
  133.  
  134.     glPushMatrix();
  135.     if (zoom) glScalef(1.5f, 1.5f, 1.f);
  136.     glColor4f(1,1,1,1);
  137.     for (i = ny+1; i; i--) {
  138.         glBegin(GL_TRIANGLE_STRIP);
  139.         for (j = nx+1; j; j--) {
  140.             glTexCoord2fv(mp);
  141.             glVertex3fv(mp+4);
  142.             glTexCoord2fv(mp+8);
  143.             glVertex3fv(mp+12);    mp += 16;
  144.         }
  145.         glEnd();
  146.     }
  147.     glPopMatrix();
  148. }
  149.  
  150. static void
  151. help(void) {
  152.     printf("'h'      - help\n");
  153.     printf("'left'   - pan left\n");
  154.     printf("'right'  - pan right\n");
  155.     printf("'up'     - pan up\n");
  156.     printf("'down'   - pan down\n");
  157.     printf("'t'      - toggle texture memory display\n");
  158.     printf("'g'         - toggle grid\n");
  159.     printf("'x'         - toggle auto pan\n");
  160.     printf("'z'      - toggle zoom\n");
  161. }
  162.  
  163. static void
  164. gfunc(void) {
  165.     grid ^= 1;
  166. }
  167.  
  168. static void
  169. tfunc(void) {
  170.     texture ^= 1;
  171. }
  172.  
  173. static void anim(void);
  174.  
  175. static void
  176. xfunc(void) {
  177.     static int state;
  178.     glutIdleFunc((state ^= 1) ? anim : NULL);
  179. }
  180.  
  181. static void
  182. zfunc(void) {
  183.     zoom ^= 1;
  184. }
  185.  
  186. #define CLAMP(v)    { int w = TSIZE/2; \
  187.                 if (v < w) v = w; \
  188.                 else if (v > TILES*TILESIZE-w) v = TILES*TILESIZE-w; }
  189. static void
  190. up(void) {
  191.     y += 8;
  192.     CLAMP(y);
  193. }
  194.  
  195. static void
  196. pfunc(void) {
  197.     static int delta = -1;
  198.     int xx = x + delta;
  199.     x += delta; CLAMP(x);
  200.     y += delta; CLAMP(y);
  201.     if (x != xx) delta = -delta;
  202. }
  203.  
  204. static void
  205. down(void) {
  206.     y -= 8;
  207.     CLAMP(y);
  208. }
  209.  
  210. static void
  211. right(void) {
  212.     x += 8;
  213.     CLAMP(x);
  214. }
  215.  
  216. static void
  217. left(void) {
  218.     x -= 8;
  219.     CLAMP(x);
  220. }
  221.  
  222. static void
  223. anim(void) {
  224.     static int delta = -1;
  225.     int xx = x + delta;
  226.     x += delta;
  227.     CLAMP(x);
  228.     y += delta;
  229.     CLAMP(y);
  230.     if (x != xx) delta = -delta;
  231.     glutPostRedisplay();
  232. }
  233.  
  234.  
  235. static void
  236. loadtiles(void) {
  237.     int lx, rx, ty, by;    /* image bounding box */
  238.     static int ox = TILES*TILESIZE/2, oy = TILES*TILESIZE/2;  /* image origin */
  239.     static int ot = 0, os = 0;
  240.     int dx = 0, dy = 0, nx = -1, ny = -1;
  241.     float trx, try;
  242. #define S_TSIZE    (TSIZE-TILESIZE)    /* visible portion of texture = TSIZE less one tile for slop */
  243.  
  244.     /* calculate tile #'s at corners of visible region */
  245.     lx = x - S_TSIZE/2;
  246.     rx = lx + S_TSIZE;
  247.     by = y - S_TSIZE/2;
  248.     ty = by + S_TSIZE;
  249.     lx /= TILESIZE; rx /= TILESIZE;
  250.     by /= TILESIZE; ty /= TILESIZE;
  251.  
  252.     dx = ((x - S_TSIZE/2)/TILESIZE) - ((ox - S_TSIZE/2)/TILESIZE);
  253.     
  254.     nx = lx; ny = by;
  255.     if (dx < 0) {
  256.     /* add on left */
  257.     os -= TILESIZE;
  258.     if (os < 0) os += TSIZE;
  259.     nx = lx;
  260.     } else if (dx > 0) {
  261.     nx = rx;
  262.     }
  263.  
  264.     dy = ((y - S_TSIZE/2) / TILESIZE) - ((oy - S_TSIZE/2) / TILESIZE);
  265.     if (dy > 0) {
  266.     /* add on bottom */
  267.     ny = ty;
  268.     } else if (dy < 0) {
  269.     /* add on top */
  270.     ot -= TILESIZE;
  271.     if (ot < 0) ot += TSIZE;
  272.     ny = by;
  273.     }
  274. if (dx || dy) printf("dx %d dy %d   lx %d rx %d   by %d ty %d   nx %d ny %d   os %d ot %d\n", dx, dy, lx, rx, by, ty, nx, ny, os, ot);
  275.     if (dx) {
  276.     int t;
  277.     for(t = 0; t < TSIZE; t += TILESIZE) {
  278.         glTexSubImage2D(GL_TEXTURE_2D, 0, os, (t+ot) % TSIZE, TILESIZE,
  279.                  TILESIZE, GL_RGBA, GL_UNSIGNED_BYTE,
  280.                  tiles[ny+t/TILESIZE][nx].data);
  281. printf("load %d %d  %d %d\n", nx, ny+t/TILESIZE, os, (t+ot) % TSIZE);
  282.     }
  283.     }
  284.  
  285.     if (dy) {
  286.     int s;
  287.     for(s = 0; s < TSIZE; s += TILESIZE) {
  288.         glTexSubImage2D(GL_TEXTURE_2D, 0, (s+os) % TSIZE, ot, TILESIZE,
  289.                  TILESIZE, GL_RGBA, GL_UNSIGNED_BYTE,
  290.                  tiles[ny][nx+s/TILESIZE].data);
  291. printf("load %d %d  %d %d\n", nx+s/TILESIZE, ny, (s+os) % TSIZE, ot);
  292.     }
  293.     }
  294.     if (dx > 0) {
  295.     os += TILESIZE;
  296.     if (os >= TSIZE) os -= TSIZE;
  297.     }
  298.     if (dy > 0) {
  299.     ot += TILESIZE;
  300.     if (ot >= TSIZE) ot -= TSIZE;
  301.     }
  302.     ox = x; oy = y;
  303.     glMatrixMode(GL_TEXTURE);
  304.     glLoadIdentity();
  305.     trx = (float)((x-TILES*TILESIZE/2) % TSIZE)/TSIZE;
  306.     try = (float)((y-TILES*TILESIZE/2) % TSIZE)/TSIZE;
  307.     glTranslatef(trx, try, 0.f);
  308.     glMatrixMode(GL_MODELVIEW);
  309. }
  310.  
  311. static void
  312. init(char *filename) {
  313.     int i;
  314.  
  315.     mesh0(-1.f,1.f,-1.f,1.f,0.f,1.f,0.f,1.f,0.f,64,64);
  316.     if (filename) {
  317.     image = read_texture(filename, &width, &height, &components);
  318.     if (image == NULL) {
  319.         fprintf(stderr, "Error: Can't load image file \"%s\".\n",
  320.             filename);
  321.         exit(EXIT_FAILURE);
  322.     } else {
  323.         printf("%d x %d image loaded\n", width, height);
  324.     }
  325.     if (components < 3 || components > 4) {
  326.         printf("must be RGB or RGBA image\n");
  327.         exit(EXIT_FAILURE);
  328.     }
  329.     } else {
  330.     int i, j;
  331.     components = 4; width = height = TSIZE;
  332.     image = (unsigned *) malloc(width*height*sizeof(unsigned));
  333.     for (j = 0; j < height; j++)
  334.         for (i = 0; i < width; i++) {
  335.         if (i & 1)
  336.             image[i+j*width] = 0xff;
  337.         else
  338.             image[i+j*width] = 0xff00;
  339.         if (j&1)
  340.             image[i+j*width] |= 0xff0000;
  341.         }
  342.  
  343.     }
  344.     if (width % TILESIZE || height % TILESIZE) {
  345. #define TXSIZE 192
  346.     unsigned *newimage = malloc(TXSIZE*TXSIZE*sizeof *newimage);
  347.     gluScaleImage(GL_RGBA, width, height, GL_UNSIGNED_BYTE, image,
  348.         TXSIZE, TXSIZE, GL_UNSIGNED_BYTE, newimage);
  349.     free(image);
  350.     image = newimage; width = height = TXSIZE; components = 4;
  351.     }
  352.     tile_image(image);
  353.     glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
  354.     glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
  355.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  356.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  357.     glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
  358.     glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
  359.  
  360.     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, TSIZE,
  361.                  TSIZE, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
  362.     for(i = 0; i < TILES; i++) {
  363.     int j;
  364.     for(j = 0; j < TILES; j++) {
  365.         glTexSubImage2D(GL_TEXTURE_2D, 0, i*TILESIZE, j*TILESIZE, TILESIZE,
  366.          TILESIZE, GL_RGBA, GL_UNSIGNED_BYTE, 
  367.          tiles[(TILES-TSIZE/TILESIZE)/2+j][(TILES-TSIZE/TILESIZE)/2+i].data);
  368.     }
  369.     }
  370.     glEnable(GL_TEXTURE_2D);
  371.  
  372.     glMatrixMode(GL_PROJECTION);
  373.     glLoadIdentity();
  374.     gluPerspective(90.,1.,.1,10.);
  375.     glMatrixMode(GL_MODELVIEW);
  376.     glLoadIdentity();
  377.     glTranslatef(0.,0.,-1.0);
  378.     glLineWidth(3.0);
  379.     glClearColor(.25, .25, .25, .25);
  380.  
  381.     /* start at center of image */
  382.     x = TILES*TILESIZE/2;
  383.     y = TILES*TILESIZE/2;
  384. }
  385.  
  386. void
  387. showgrid(void) {
  388.     GLfloat mat[16];
  389.     int i;
  390.  
  391.     glPushMatrix();
  392.     glDisable(GL_TEXTURE_2D);
  393.     glPushMatrix();
  394.     glColor3f(0.f, 0.f, 0.f);
  395.     if (!zoom) glScalef(1.f/1.5f, 1.f/1.5f, 1.f);
  396.     glBegin(GL_LINE_LOOP);
  397.     glVertex2f(-1.f,-1.f);
  398.     glVertex2f(-1.f, 1.f);
  399.     glVertex2f( 1.f, 1.f);
  400.     glVertex2f( 1.f,-1.f);
  401.     glEnd();
  402.     glPopMatrix();
  403.  
  404.     glGetFloatv(GL_TEXTURE_MATRIX,mat);
  405.     glPushMatrix();
  406.     if (zoom) glScalef(1.5f,1.5f,1.f);
  407.     glTranslatef(-1.f,-1.f,-1.f);
  408.     glScalef(2.f,2.f,1.f);
  409.     glTranslatef(-mat[12], -mat[13], 1.0f);
  410. #if 1
  411.     glColor3f(1.f,1.f,1.f);
  412. #else
  413.     glColor3f(1.f,0.f,0.f);
  414. #endif
  415.     glBegin(GL_LINES);
  416.     for(i = -TSIZE; i <= 2*TSIZE; i+=TILESIZE) {
  417.     GLfloat x = (GLfloat)i/(GLfloat)TSIZE;
  418.     glVertex2f(-1.f,x);
  419.     glVertex2f(2.f,x);
  420.     glVertex2f(x,-1.f);
  421.     glVertex2f(x,2.f);
  422.     }
  423.     glEnd();
  424.     glPopMatrix();
  425.     glEnable(GL_TEXTURE_2D);
  426.     glPopMatrix();
  427. }
  428.  
  429. static void
  430. drawtexture(void) {
  431.     glMatrixMode(GL_TEXTURE);
  432.     glPushMatrix();
  433.     glLoadIdentity();
  434.     glColor3f(1.f,1.f,1.f);
  435.     glBegin(GL_QUADS);
  436.     glTexCoord2f(0.f, 0.f); glVertex2f(-1.f, -1.f);
  437.     glTexCoord2f(0.f, 1.f); glVertex2f(-1.f,  1.f);
  438.     glTexCoord2f(1.f, 1.f); glVertex2f( 1.f,  1.f);
  439.     glTexCoord2f(1.f, 0.f); glVertex2f( 1.f, -1.f);
  440.     glEnd();
  441.     glPopMatrix();
  442.     glMatrixMode(GL_MODELVIEW);
  443. }
  444.  
  445. static void
  446. display(void) {
  447.     glClear(GL_COLOR_BUFFER_BIT);
  448.     loadtiles();
  449.     if (texture) {
  450.     drawtexture();
  451.     } else {
  452.     drawmesh(64,64);
  453.     if (grid) showgrid();
  454.     }
  455.     glutSwapBuffers();
  456. }
  457.  
  458. static void
  459. reshape(int w, int h) {
  460.     glViewport(0, 0, w, h);
  461. }
  462.  
  463. /*ARGSUSED1*/
  464. static void
  465. key(unsigned char key, int x, int y) {
  466.     switch(key) {
  467.     case 'h': help(); break;
  468.     case 'g': gfunc(); break;
  469.     case 't': tfunc(); break;
  470.     case 'z': zfunc(); break;
  471.     case 'x': xfunc(); break;
  472.     case 'p': pfunc(); break;
  473.     case '\033': exit(EXIT_SUCCESS); break;
  474.     default: break;
  475.     }
  476.     glutPostRedisplay();
  477. }
  478.  
  479. /*ARGSUSED1*/
  480. static void
  481. special(int key, int x, int y) {
  482.     switch(key) {
  483.     case GLUT_KEY_UP:    up(); break;
  484.     case GLUT_KEY_DOWN:    down(); break;
  485.     case GLUT_KEY_LEFT:    left(); break;
  486.     case GLUT_KEY_RIGHT:right(); break;
  487.     }
  488.     glutPostRedisplay();
  489. }
  490.  
  491. int main(int argc, char* argv[]) {
  492.     glutInitWindowSize(512, 512);
  493.     glutInit(&argc, argv);
  494.     glutInitDisplayMode(GLUT_RGBA|GLUT_DOUBLE);
  495.     (void)glutCreateWindow(argv[0]);
  496.     init(argv[1]);
  497.     glutDisplayFunc(display);
  498.     glutKeyboardFunc(key);
  499.     glutSpecialFunc(special);
  500.     glutReshapeFunc(reshape);
  501.     glutMainLoop();
  502.     return 0;
  503. }
  504.